package com.grace.system.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.grace.common.constant.CacheConstants;
import com.grace.common.constant.UserConstants;
import com.grace.common.enums.ConfigValueTypeEnum;
import com.grace.common.enums.SysConfigGroups;
import com.grace.common.exception.ServiceException;
import com.grace.common.properties.PropertyEnum;
import com.grace.common.utils.StringUtils;
import com.grace.redis.utils.RedisCache;
import com.grace.system.domain.SysConfig;
import com.grace.system.mapper.SysConfigMapper;
import com.grace.system.service.ISysConfigService;
import com.grace.system.service.ISysSearchConfigService;

/**
 * 参数配置 服务层实现
 * 
 * @author grace
 */
@Service
public class SysConfigServiceImpl implements ISysConfigService {

    @Autowired
    private SysConfigMapper configMapper;

    @Autowired
    private ISysSearchConfigService searchConfigService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        loadingConfigCache();
    }

    /**
     * 查询参数配置信息
     * 
     * @param configGroup 参数组
     * @param configKey   参数键名
     * @return 参数配置信息
     */
    public SysConfig selectConfigByGk(String configGroup, String configKey) {
        SysConfig config = new SysConfig();
        config.setConfigKey(configKey);
        config.setConfigGroup(configGroup);
        return this.selectConfig(config);
    }

    /**
     * 新增参数配置
     * 
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int insertConfig(SysConfig config) {
        int row = configMapper.insertConfig(config);
        checkConfigValueType(config.getConfigValueType(), config.getConfigValue());
        if (row > 0) {
            redisCache.setCacheObject(getCacheKey(config.getConfigGroup(), config.getConfigKey()),
                    config.getConfigValue());
        }
        return row;
    }

    /**
     * 修改参数配置ById
     * 
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int updateConfigById(SysConfig config) {
        SysConfig temp = searchConfigService.selectConfigById(config.getConfigId());
        if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
            redisCache.deleteObject(getCacheKey(temp.getConfigGroup(), temp.getConfigKey()));
        }
        checkConfigValueType(config.getConfigValueType(), config.getConfigValue());
        int row = configMapper.updateConfigById(config);
        if (row > 0) {
            redisCache.setCacheObject(getCacheKey(config.getConfigGroup(), config.getConfigKey()),
                    config.getConfigValue());
        }
        return row;
    }

    /**
     * 修改参数配置通过配置组
     * 
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public int updateConfigByGk(SysConfig config) {
        SysConfig rsConfig = this.selectConfigByGk(config.getConfigGroup(), config.getConfigKey());
        if (rsConfig == null) {
            throw new ServiceException(
                    String.format("参数key为【%1$s】,group为【%2$s】不能存在", config.getConfigKey(), config.getConfigGroup()));
        } else {
            checkConfigValueType(rsConfig.getConfigValueType(), config.getConfigValue());
        }
        int row = configMapper.updateConfigByGk(config);
        if (row > 0) {
            redisCache.setCacheObject(getCacheKey(config.getConfigGroup(), config.getConfigKey()),
                    config.getConfigValue());
        }
        return row;
    }

    /**
     * 批量删除参数信息
     * 
     * @param configIds 需要删除的参数ID
     */
    @Override
    public void deleteConfigByIds(Long[] configIds) {
        for (Long configId : configIds) {
            SysConfig config = selectConfigById(configId);
            if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
                throw new ServiceException(String.format("内置参数ID为【%1$s】不能删除 ", config.getConfigId()));
            }
            configMapper.deleteConfigById(configId);
            redisCache.deleteObject(getCacheKey(config.getConfigGroup(), config.getConfigKey()));
        }
    }

    /**
     * 删除参数配置对象ByGk
     * 
     * @param config
     * @return 结果
     */
    @Override
    public int deleteConfigByGk(String configGroup, String configKey) {
        int re = 0;
        if (SysConfigGroups.getValues().contains(configGroup)) {
            throw new ServiceException(String.format("【%1$s】为系统配置组,当前组成员不能删除 ", configGroup));
        } else {
            SysConfig config = this.selectConfigByGk(configGroup, configKey);
            if (config != null) {
                if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
                    throw new ServiceException(String.format("内置参数ID为【%1$s】不能删除 ", config.getConfigId()));
                }
                re = configMapper.deleteConfigById(config.getConfigId());
            }
            redisCache.deleteObject(getCacheKey(configGroup, configKey));
            return re;
        }

    }

    @Override
    public int deleteConfigByGroup(String configGroup) {
        int re = 0;
        SysConfig sysConfig = new SysConfig();
        sysConfig.setConfigGroup(configGroup);
        List<SysConfig> configs = this.selectConfigList(sysConfig);
        for (SysConfig iter : configs) {
            re += this.deleteConfigByGk(iter.getConfigGroup(), iter.getConfigKey());
        }
        return re;
    }

    /**
     * 加载参数缓存数据
     */
    @Override
    public void loadingConfigCache() {
        List<SysConfig> configsList = this.selectConfigList(new SysConfig());
        for (SysConfig config : configsList) {
            redisCache.setCacheObject(getCacheKey(config.getConfigGroup(), config.getConfigKey()),
                    config.getConfigValue());
        }
    }

    /**
     * 清空参数缓存数据
     */
    @Override
    public void clearConfigCache() {
        Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
        redisCache.deleteObject(keys);
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingConfigCache();
    }

    /**
     * 校验配置组是否唯一
     * 与配置key是否唯一
     * 
     * @param config 参数配置信息
     * @return 结果
     */
    @Override
    public boolean checkConfigGkUnique(SysConfig config) {
        Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
        SysConfig info = this.selectConfig(config);
        if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 升级配置
     * 
     * @param 配置map
     * @param login 用户名
     */
    @Override
    public int updatesByMap(Map<String, Object> map, String login) {
        int i = 0;
        String configGroup = map.get("configGroup").toString();
        if (StringUtils.isEmpty(configGroup)) {
            throw new ServiceException("配置组能为空!");
        }
        map.remove("configGroup");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            SysConfig sysConfig = new SysConfig();
            sysConfig.setConfigKey(entry.getKey());

            sysConfig.setConfigGroup(configGroup);
            SysConfig rsConfig = this.selectConfigByGk(sysConfig.getConfigGroup(), sysConfig.getConfigKey());
            // 存在执行更新操作
            if (StringUtils.isNotNull(rsConfig)) {
                sysConfig.setUpdateBy(login);
                sysConfig.setConfigValueType(rsConfig.getConfigValueType());
                if (ConfigValueTypeEnum.ARRAY.ordinal() == rsConfig.getConfigValueType().intValue()
                        && entry.getValue() instanceof ArrayList) {
                    sysConfig.setConfigValue(StringUtils.join((ArrayList) (entry.getValue()), ","));
                } else {
                    sysConfig.setConfigValue(entry.getValue().toString());
                }
                this.updateConfigByGk(sysConfig);
            }
            // 不存在执行插入操作
            else {
                sysConfig.setConfigName(entry.getKey());
                sysConfig.setConfigValue(entry.getValue().toString());
                sysConfig.setCreateBy(login);
                sysConfig.setConfigValueType(ConfigValueTypeEnum.STRING.ordinal());
                this.insertConfig(sysConfig);
            }
            i = +1;
        }
        this.clearConfigCache();
        return i;
    }

    @Override
    public SysConfig selectConfig(SysConfig sysConfig) {

        return searchConfigService.selectConfig(sysConfig);
    }

    @Override
    public SysConfig selectConfigById(Long configId) {

        return searchConfigService.selectConfigById(configId);
    }

    @Override
    public String selectConfigValueByGk(String configGroup, String configKey) {

        return searchConfigService.selectConfigValueByGk(configGroup, configKey);
    }

    @Override
    public List<SysConfig> selectConfigList(SysConfig config) {

        return searchConfigService.selectConfigList(config);
    }

    @Override
    public List<String> selectConfigGroupList() {

        return searchConfigService.selectConfigGroupList();
    }

    @Override
    public Map<String, SysConfig> selectConfigMap(SysConfig config) {

        return searchConfigService.selectConfigMap(config);
    }

    @Override
    public Map<String, String> selectConfigValueMap(SysConfig config) {

        return searchConfigService.selectConfigValueMap(config);
    }

    @Override
    public Map<String, SysConfig> selectConfigMapByGroupName(String configGroup) {

        return searchConfigService.selectConfigMapByGroupName(configGroup);
    }

    @Override
    public Map<String, String> selectConfigValueMapByGroupName(String configGroup) {

        return searchConfigService.selectConfigValueMapByGroupName(configGroup);
    }

    @Override
    public String selectConfigDefaultValue(String groupName, PropertyEnum propertyEnum) {

        return searchConfigService.selectConfigDefaultValue(groupName, propertyEnum);
    }

    /**
     * 判断是否符合预期类型
     * 
     * @param type
     * @param object
     * @return
     */
    private void checkConfigValueType(Integer type, Object object) {
        boolean result = false;
        if (type == ConfigValueTypeEnum.BOOLEAN.ordinal()) {
            result = "true".equals(object) || "false".equals(object);
        } else if (type == ConfigValueTypeEnum.NUMBER.ordinal()) {
            result = NumberUtils.isDigits(object.toString());
        } else if (type == ConfigValueTypeEnum.FLOAT.ordinal()) {
            result = NumberUtils.isCreatable(object.toString());
        } else {
            result = true;
        }
        if (!result)
            throw new ServiceException(String.format("预期类型检测不通过类型【%1$s,参数%2$s】", type, object));
    }

    /**
     * 设置cache key
     * 
     * @param configGroup 参数组
     * @param configKey   参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configGroup, String configKey) {
        return ISysSearchConfigService.getCacheKey(configGroup, configKey);
    }

    @Override
    public Map<String, Object> selectConfigValueObjMap(String configGroup) {

        return searchConfigService.selectConfigValueObjMap(configGroup);
    }

    @Override
    public boolean selectCaptchaEnabled(String groupName) {

        return searchConfigService.selectCaptchaEnabled(groupName);
    }

}
